﻿using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using StackExchange.Profiling;
using StackExchange.Profiling.Storage;
using System;
using System.Linq;

namespace BJoin.Application.WebApi.Middlewares
{
    public static class MiniProfilerExtensions
    {
        public static IServiceCollection AddProfiler(this IServiceCollection services, IHostEnvironment environment, IConfiguration config)
        {
            if (!environment.CanProfiler(config)) return services;
            services.AddMiniProfiler(options =>
            {
                // All of this is optional. You can simply call .AddMiniProfiler() for all defaults

                // (Optional) Path to use for profiler URLs, default is /mini-profiler-resources
                options.RouteBasePath = "/profiler";

                //skip the special path
                options.IgnorePath("script");
                options.ShouldProfile = request =>
                {
                    var ignoredPaths = config.GetSection("MiniProfilerIgnoredPaths").Get<string[]>();//skip
                    if (ignoredPaths != null
                        && ignoredPaths.Any(o => request.Path.Value.Contains(o, StringComparison.OrdinalIgnoreCase)))
                    {
                        return false;
                    }
                    return true;
                };

                // (Optional) Control storage
                // (default is 30 minutes in MemoryCacheStorage)
                (options.Storage as MemoryCacheStorage).CacheDuration = TimeSpan.FromMinutes(60);

                // (Optional) Control which SQL formatter to use, InlineFormatter is the default
                options.SqlFormatter = new StackExchange.Profiling.SqlFormatters.InlineFormatter();

                // (Optional) To control authorization, you can use the Func<HttpRequest, bool> options:
                // (default is everyone can access profilers)
                //options.ResultsAuthorize = request => MyGetUserFunction(request).CanSeeMiniProfiler;
                //options.ResultsListAuthorize = request => MyGetUserFunction(request).CanSeeMiniProfiler;

                // (Optional)  To control which requests are profiled, use the Func<HttpRequest, bool> option:
                // (default is everything should be profiled)
                //options.ShouldProfile = request => MyShouldThisBeProfiledFunction(request);

                // (Optional) Profiles are stored under a user ID, function to get it:
                // (default is null, since above methods don't use it by default)
                //options.UserIdProvider = request => MyGetUserIdFunction(request);

                // (Optional) Swap out the entire profiler provider, if you want
                // (default handles async and works fine for almost all applications)
                //options.ProfilerProvider = new MyProfilerProvider();

                // (Optional) You can disable "Connection Open()", "Connection Close()" (and async variant) tracking.
                // (defaults to true, and connection opening/closing is tracked)
                options.TrackConnectionOpenClose = true;
            });

            return services;
        }

        public static bool CanProfiler(this IHostEnvironment environment, IConfiguration configuration = null)
        {
            var defaultUse = environment.IsDevelopment() || environment.IsStaging();
            if (configuration == null) return defaultUse;
            //true, false, null
            var useProfiler = configuration.GetValue<bool?>("UseProfiler", null);
            return useProfiler ?? defaultUse;
        }
        /// <summary>
        /// Adds middleware for profiling HTTP requests.
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseProfiler(this IApplicationBuilder app, IHostEnvironment env, IConfiguration config)
        {
            if (!env.CanProfiler(config)) return app;
            return app.UseMiniProfiler();
        }
    }
}
